package vg.services.graph_view_manager.realization.graph_comparison.algorithm;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

// TODO
public class SolutionSet {
	private float[][] relationshipTable;
	private float barrier;
	private List<MCSVertexGroup> verticalGroup;
	private List<MCSVertexGroup> horizontalGroup;
	private List<MCSVertexGroup> currGroupSolution;
	
	public SolutionSet(float[][] relationshipTable, float barrier) {
		this.relationshipTable = relationshipTable;
		this.barrier = barrier;
		init();
	}
	
	public Solution next() {
		boolean check = false;
		for (MCSVertexGroup buf : currGroupSolution) {
			if (buf.hasNext()) {
				buf.next();
				check = true;
				break;
			} else {
				buf.resetIndex();
			}
		}
		
		if (!check) {
			for (MCSVertexGroup buf : verticalGroup) {
				if (buf.hasNext()) {
					buf.next();
					check = true;
					break;
				} else {
					buf.resetIndex();
				}
			}
			if (check) {
				initCurrGroupSolution();
			} else {
				return null;
			}
		}
		
		return curr();
	}
	
	public Solution curr() {
		MCSVertex[] solutionArray = new MCSVertex[currGroupSolution.size()];
		int i = 0;
		for (MCSVertexGroup buf : currGroupSolution) {
			solutionArray[i++] = buf.curr();
		}
		return new Solution(solutionArray);
	}
	
	public boolean hasNext() {
		if (currGroupSolution != null && currGroupSolution.size() > 0) {
			for (MCSVertexGroup buf : currGroupSolution) {
				if (buf.hasNext())
					return true;
			}
		}
		
		if (verticalGroup != null && verticalGroup.size() > 0) {
			for (MCSVertexGroup buf : verticalGroup) {
				if (buf.hasNext())
					return true;
			}	
		}
		
		return false;
	}
	
	public BigDecimal roughSize() {
		BigDecimal size = new BigDecimal(1);
		for (MCSVertexGroup buf : verticalGroup) {
			size = size.multiply(new BigDecimal(buf.size()));
		}

		for (MCSVertexGroup buf : horizontalGroup) {
			size = size.multiply(new BigDecimal(buf.size()));
		}
		
		return size;
	}

//=============================================================================
//-----------------PRIVATE METHODS---------------------------------------------
	private void init() {
		int n = relationshipTable.length;
		int m = relationshipTable[0].length;
		
		MCSVertexGroup[] verGroup = new MCSVertexGroup[n];
		for (int i = 0; i < n; i++) {
			verGroup[i] = new MCSVertexGroup();
		}

		MCSVertexGroup[] horGroup = new MCSVertexGroup[m];
		for (int j = 0; j < m; j++) {
			horGroup[j] = new MCSVertexGroup();
		}
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				if (relationshipTable[i][j] >= barrier) {
					MCSVertex e = new MCSVertex(i, j);
					verGroup[i].push(e);
					horGroup[j].push(e);
				}
			}
		}
		
		verticalGroup = new ArrayList<MCSVertexGroup>();
		for (int i = 0; i < n; i++) {
			if (verGroup[i].size() > 0)
				verticalGroup.add(verGroup[i]);
		}

		horizontalGroup = new ArrayList<MCSVertexGroup>();
		for (int i = 0; i < n; i++) {
			if (horGroup[i].size() > 0)
				horizontalGroup.add(horGroup[i]);
		}
		
		initCurrGroupSolution();
	}
	
	private void initCurrGroupSolution() {
		// build vertical solution
		MCSVertex[] preventVerticalSolutionArray = new MCSVertex[verticalGroup.size()];
		int i = 0;
		for (MCSVertexGroup buf : verticalGroup) {
			preventVerticalSolutionArray[i++] = buf.curr();
		}
		
		// build horizontal solution
		MCSVertexGroup[] preventHorizontalSolutionArray = new MCSVertexGroup[horizontalGroup.size()];
		for (i = 0; i < horizontalGroup.size(); i++) {
			preventHorizontalSolutionArray[i] = new MCSVertexGroup();
		}
		for (MCSVertex bufEdge : preventVerticalSolutionArray) {
			i = 0;
			for (MCSVertexGroup bufGroup : horizontalGroup) {
				if (bufGroup.contains(bufEdge)) {
					preventHorizontalSolutionArray[i].push(bufEdge);
					break;
				}
				i++;
			}
		}
		
		// clear empty groups
		currGroupSolution = new ArrayList<MCSVertexGroup>();
		for (MCSVertexGroup buf : preventHorizontalSolutionArray) {
			if (buf != null && buf.size() > 0) {
				currGroupSolution.add(buf);
			}
		}
	}
}
